
#include <memory.h>
#include <stdio.h>
#include "../basic/operator.h"

/*
Cell* make_exception(Scheme *sc, const char *code, const char *desc, OperatorFunc handler, Cell* data) {
	// (new-object '() Exception make-exception code desc handler data)
	sc->args = G_NIL;
	sc->args = cons(sc, data, sc->args);
	sc->args = cons(sc, make_proc(sc, handler), sc->args);
	sc->args = cons(sc, make_string(sc, desc), sc->args);
	sc->args = cons(sc, make_string(sc, code), sc->args);
	sc->args = cons(sc, make_string(sc, "make-exception"), sc->args);
	// sc->args = cons(sc, make_class(sc, EXCEPTION_TYPE), sc->args);
	sc->args = cons(sc, G_NIL, sc->args);

	return op_make_object(sc);
}
*/

Cell* make_exception(Scheme *sc, const char *code, const char *desc, Cell* handler, Cell* data) {
	Cell *ex = G_NIL;
	ex = cons(sc, data, ex);
	ex = cons(sc, handler, ex);
	ex = cons(sc, make_string(sc, desc), ex);
	ex = cons(sc, make_string(sc, code), ex);
	ex->_type = EXCEPTION_TYPE;
	return ex;
}

Cell* make_default_exception(Scheme *sc, const char *code, const char *desc) {
	return make_exception(sc, code, desc, cell_op_default_exception_handler, G_NIL);
}

Cell* make_default_exception_1(Scheme *sc, const char *code, const char *desc, const char *arg1) {
	char tmp[1024];
	snprintf(tmp, 1024, desc, arg1);
	return make_exception(sc, code, tmp, cell_op_default_exception_handler, G_NIL);
}

Cell* make_default_exception_2(Scheme *sc, const char *code, const char *desc, const char *arg1, const char *arg2) {
	char tmp[1024];
	snprintf(tmp, 1024, desc, arg1, arg2);
	return make_exception(sc, code, desc, cell_op_default_exception_handler, G_NIL);
}

/*
static Cell* find_property(Scheme *sc, const char *propertyName) {
	return find_slot_by_name(sc, sc->obj, propertyName);
}
*/

Cell* op_default_exception_handler(Scheme *sc) {
	Cell* code = first(sc->args);
	Cell* desc = second(sc->args);
	fprintf(stderr, "Catch a exception [");
	fprintf(stderr, code->_string);
	fprintf(stderr, "]: ");
	fprintf(stderr, desc->_string);
	sc->returnValue = G_TRUE;
	return pop_callstack(sc);
}

void init_exception_operators(Scheme *sc) {
	ADD_OPERATOR(sc, "handle-exception", default_exception_handler);
}

void init_exception_constants(Scheme *sc) {
	E_DIVISION_BY_ZERO = make_default_exception(sc, "DIVISION_BY_ZERO", "/: division by zero.");
	E_NOT_A_REAL = make_default_exception(sc, "NOT_A_REAL", "Not a real number.");
	E_NOT_A_NUMBER = make_default_exception(sc, "NOT_A_NUMBER", "Not a number.");
    //E_INVALID_TYPE;
}

int eqe(Cell *a, Cell *b) {
    if (strcmp(a->_type, EXCEPTION_TYPE) != 0) {
        return FALSE;
    }
    if (strcmp(b->_type, EXCEPTION_TYPE) != 0) {
        return FALSE;
    }
    if (strcmp(first(a)->_string, first(b)->_string) != 0) {
        return FALSE;
    }
    if (strcmp(second(a)->_string, second(b)->_string) != 0) {
        return FALSE;
    }
    return TRUE;
}

/*

Cell* error_helper(Scheme *sc, const char * errorDesc, Cell* arg) {
	//查找释放有处理错误的钩子函数
	Cell* symbol = find_slot_in_env(sc, sc->env, sc->sym_error_hook, TRUE);
	//如果找到了钩子函数，由钩子函数来处理这个错误
	if (symbol != G_NIL) {
		if (arg != NULL) {
			sc->code = cons(sc, cons(sc, sc->sym_quote, cons(sc, arg, G_NIL)),
					G_NIL);
			//结果（用lisp表示）类似这样：(sc->sym_quote arg)
		} else {
			sc->code = G_NIL;
		}
		sc->code = cons(sc, make_string(sc, errorDesc), sc->code);
		//结果（用lisp表示）类似这样：(error_desc sc->sym_quote arg)
		set_immutable(car(sc->code));
		sc->code = cons(sc, slot_value_in_env(symbol), sc->code);
		//结果（用lisp表示）类似这样：(slot_value_in_env(symbol)  error_desc sc->sym_quote arg)
		sc->op = op_eval;
		return &g_true;
	} else {
		if (arg != NULL) {
			sc->args = cons(sc, arg, G_NIL);
		} else {
			sc->args = G_NIL;
		}
		sc->args = cons(sc, make_string(sc, errorDesc), sc->args);
		//结果（用lisp表示）类似这样：(error_desc arg)
		set_immutable(car(sc->args));
		sc->op = op_err;
		return &g_true;
	}
}

*/

